import { _decorator, resources, Asset, error } from "cc";
import Singleton from "../Base/Singleton";
import { IModel } from "../Common/index";
import DataManager from "./DataManager";

interface IItem {
  cb: Function;
  ctx: unknown;
}
interface ICallApiRet<T>{
  success:boolean;
  res?:T;
  error?:Error;
}

export class NetworkManager extends Singleton {
  static get Instance() {
    return super.GetInstance<NetworkManager>();
  }
  
  isConnected=false;//是否连接
  port=9876;
  ws:WebSocket;
   private map: Map<string, Array<IItem>> = new Map();
  connect() {
  return new Promise((resolve, reject) => {
    if(this.isConnected){
      resolve(true);
      return;
    }
        this.ws = new WebSocket(`ws://192.168.18.166:${this.port}`); // 替换为实际服务器IP
        this.ws.onopen=()=>{
          this.isConnected=true;
            resolve(true)
        }
        this.ws.onclose=()=>{
            this.isConnected=false;
            reject(false)
        }
        this.ws.onerror=(e)=>{  
          this.isConnected=false;
            console.log(e);
            reject(false)
        }
        this.ws.onmessage=(e)=>{  
        try{
          // console.log("onmessage",e.data);
          const json=JSON.parse(e.data);
          const {name,data}=json;
          if (this.map.has(name)) {
            this.map.get(name).forEach(({ cb, ctx }) => {
              cb.apply(ctx, Array.isArray(data) ? data : [data]);
            });
          }
        }catch(e){
          console.error(e);
        }
   
        }

    });
  }
  callApi<T extends keyof IModel["api"] >(name:T,data:IModel["api"][T]["req"]):Promise<ICallApiRet<IModel["api"][T]["res"]>>{
    return new Promise((resolve)=>{
      try {
        const timer =setTimeout(()=>{
          resolve({success:false,error:new error("超时")});
          this.unlistenMsg(name as any,cb,null);
        },5000)
        const cb=(res)=>{
          resolve(res);
          clearTimeout(timer);
          this.unlistenMsg(name  as any,cb,null);
        }
        this.listenMsg(name as any,cb,null)
        this.sendMsg(name as any,data);
      } catch (error) {
        resolve({success:false,error:error});
      }
    })
  }

  async sendMsg<T extends keyof IModel["msg"]>(name:T,data: IModel["msg"][T]){
    const msg={
      name,
      data
    }
    //延时效果
    // await new Promise((rs) => setTimeout(rs, 2000));
    this.ws.send(JSON.stringify(msg));
  }

  listenMsg<T extends keyof IModel["msg"]>(name:T,cb:(args:IModel["msg"][T])=>void,ctx:unknown){
    if (this.map.has(name)) {
      this.map.get(name).push({ cb, ctx });
    } else {
      this.map.set(name, [{ cb, ctx }]);
    }
  }
  unlistenMsg<T extends keyof IModel["msg"]>(name:T,cb:(args:IModel["msg"][T])=>void,ctx:unknown){
    if (this.map.has(name)) {
      const index = this.map.get(name).findIndex((i) => cb === i.cb && i.ctx === ctx);
      index > -1 && this.map.get(name).splice(index, 1);
    }
  }
}
